<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

        class DoublyNode {
            constructor(element) {
                this.element = element;//保存元素
                this.next = null;//指向下一个节点
                this.prev = null;
            }
        }

        class DoublyLinkedList {
            constructor() {
                this.head = null;
                this.length = 0;
                this.tail = null;//尾部节点
            }
            //append(element):向末尾添加一个新的项
            append(element) {
                //1.根据element创建我们元素
                const newNode = new DoublyNode(element);
                //2.追加元素
                if (this.head === null) { //和this.length === 0 都可以进行判断
                    this.head = newNode;//头部结点
                    this.tail = newNode;//尾部结点
                } else {
                    //查询最后一个结点
                    this.tail.next = newNode;//把当前tail的下一个指向给要添加的结点
                    newNode.prev = this.tail;//把要添加的newNode结点的前一个指向当前tail
                    this.tail = newNode;//最后将  要在改变tail的指向之前，要先把当前tail的内容的指向进行调整，不然链表链接回出问题
                }
                this.length++;
            }

            //insert(position, element)：向列表的特定位置插入一个新的项
            insert(position, element) {
                const newNode = new DoublyNode(element);
                if (position < 0 || position > this.length) return false;
                if (position === 0) {
                    if (this.head === null) {
                        this.head = newNode;
                        this.tail = newNode;
                    } else {
                        newNode.next = this.head;
                        this.head.prev = newNode;
                        this.head = newNode;
                    }
                } else if (position === this.length) {
                    newNode.prev = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode;
                } else {
                    let index = 0;
                    let previous = null;
                    let current = this.head;
                    while (index++ < position) {
                        previous = current;
                        current = current.next;
                    }
                    previous.next = newNode;
                    newNode.prev = previous;
                    newNode.next = current;
                    current.prev = newNode;
                }
                this.length++;
            }
            //get(position)：获取对应位置的元素
            get(position) {
                if (position < 0 || position > this.length - 1) return false; //判断越界 
                let index = 0;
                let current = this.head;
                while (index++ < position) {
                    current = current.next;
                }
                return current.element;
            }
            //indexOf(element):返回元素在列表中的索引。如果列表中没有该元素返回-1
            indexOf(element) {
                let index = 0;
                let current = this.head;
                while (current) {
                    if (current.element === element) {
                        return index;
                    }
                    index++;
                    current = current.next
                }
                return -1;
            }
            //update(position, element): 修改某个位置的元素
            update(position ,element) {
                if(position < 0 || position > this.length - 1) return false;
                const result = this.removeAt(position);
                this.insert(position, element);
                return result;
            }
            //removeAt(position):从列表的特定的位置移除一项
            removeAt(position) {
                //越界
                if(position < 0 || position > this.length - 1) return null;
                let current = this.head;
                if(position === 0) {
                    if(this.length === 1) {
                        this.head = null;
                        this.prev = null;
                    } else {
                        this.head.next.prev = null;
                        this.head = this.head.next;
                    }
                } else if(position === this.length - 1) {
                    current = this.tail;
                    this.tail.prev.next = null;
                    this.tail = this.tail.prev;
                } else {
                    let index = 0;
                    let previous = null;
                    while(index++ < position) {
                        previous = current;
                        current = current.next;
                    }
                    previous.next = current.next;
                    current.next.prev = previous;
                }
                this.length--;
                return current.element;
            }
            //remove(element):从列表中移除一项
            remove(element) {
                const position = this.indexOf(element);
                if(position === -1) {
                    return -1;
                } else {
                    this.removeAt(position);
                }
            }
            //isEmpty()：如果链表中不包含任何元素，返回true，如果链表长度大于0则返回false
            isEmpty() {
                return this.length === 0
            }
            //size():返回链表包含的元素个数，与数组的length属性类似
            size() {
                return this.length;
            }
        }
        const doublyLinkedList = new DoublyLinkedList();
        doublyLinkedList.append(1);
        doublyLinkedList.append(2);
        doublyLinkedList.append(3);
        doublyLinkedList.append(4);
        // doublyLinkedList.insert(1, "a")
        // doublyLinkedList.insert(1, "b")
        // console.log(doublyLinkedList.get(1));
        // console.log(doublyLinkedList.indexOf("a"));
        // console.log(doublyLinkedList);
        // console.log(doublyLinkedList.removeAt(0));
        // doublyLinkedList.update(0, 10);
        // console.log(doublyLinkedList.removeAt(1));
        doublyLinkedList.update(0,"a")
        doublyLinkedList.update(1,"b")
        doublyLinkedList.update(2,"c")
        doublyLinkedList.update(3,"d")
        doublyLinkedList.remove("a");
        console.log(doublyLinkedList);

    </script>
</body>

</html>